home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_024 / csh / sub.c < prev   
C/C++ Source or Header  |  1992-05-06  |  10KB  |  477 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * Matthew Dillon, 28 Apr 1986
  6.  *
  7.  */
  8.  
  9.  
  10. #include <exec/types.h>
  11. #include <exec/exec.h>
  12. #include <libraries/dos.h>
  13. #include <libraries/dosextens.h>
  14. #include "shell.h"
  15.  
  16. #define HM_STR 0
  17. #define HM_REL 1
  18. #define HM_ABS 2
  19.  
  20. extern struct FileLock *Lock(), *DupLock(), *CurrentDir();
  21. extern struct FileLock *Clock;
  22.  
  23. char *
  24. next_word(str)
  25. register char *str;
  26. {
  27.    while (*str  &&  *str != ' '  &&  *str != 9)
  28.       ++str;
  29.    while (*str  && (*str == ' ' || *str == 9))
  30.       ++str;
  31.    return (str);
  32. }
  33.  
  34.  
  35. char *
  36. compile_av(av, start, end)
  37. char **av;
  38. {
  39.    char *cstr;
  40.    int i, len;
  41.  
  42.    len = 0;
  43.    for (i = start; i < end; ++i)
  44.       len += strlen(av[i]) + 1;
  45.    cstr = malloc(len + 1);
  46.    *cstr = '\0';
  47.    for (i = start; i < end; ++i) {
  48.       strcat (cstr, av[i]);
  49.       strcat (cstr, " ");
  50.    }
  51.    return (cstr);
  52. }
  53.  
  54.  
  55.  
  56. Free(ptr)
  57. char *ptr;
  58. {
  59.    static char *old_ptr;
  60.  
  61.    if (old_ptr)
  62.       free (old_ptr);
  63.    old_ptr = ptr;
  64. }
  65.  
  66. /*
  67.  * Add new string to history (H_head, H_tail, H_len,
  68.  *  S_histlen
  69.  */
  70.  
  71. add_history(str)
  72. char *str;
  73. {
  74.    register struct HIST *hist;
  75.  
  76.    while (H_len > S_histlen)
  77.       del_history();
  78.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  79.    if (H_head == NULL) {
  80.       H_head = H_tail = hist;
  81.       hist->next = NULL;
  82.    } else {
  83.       hist->next = H_head;
  84.       H_head->prev = hist;
  85.       H_head = hist;
  86.    }
  87.    hist->prev = NULL;
  88.    hist->line = malloc (strlen(str) + 1);
  89.    strcpy (hist->line, str);
  90.    ++H_len;
  91. }
  92.  
  93. del_history()
  94. {
  95.    if (H_tail) {
  96.       --H_len;
  97.       ++H_tail_base;
  98.       free (H_tail->line);
  99.       if (H_tail->prev) {
  100.          H_tail = H_tail->prev;
  101.          free (H_tail->next);
  102.          H_tail->next = NULL;
  103.       } else {
  104.          free (H_tail);
  105.          H_tail = H_head = NULL;
  106.       }
  107.    }
  108. }
  109.  
  110. char *
  111. get_history(ptr)
  112. char *ptr;
  113. {
  114.    register struct HIST *hist;
  115.    register int len;
  116.    int mode = HM_REL;
  117.    int num  = 1;
  118.    char *str;
  119.  
  120.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  121.       mode = HM_ABS;
  122.       num  = atoi(&ptr[1]);
  123.       goto skip;
  124.    }
  125.    switch (ptr[1]) {
  126.    case '!':
  127.       break;
  128.    case '-':
  129.       num += atoi(&ptr[2]);
  130.       break;
  131.    default:
  132.       mode = HM_STR;
  133.       str  = ptr + 1;
  134.       break;
  135.    }
  136. skip:
  137.    switch (mode) {
  138.    case HM_STR:
  139.       len = strlen(str);
  140.       for (hist = H_head; hist; hist = hist->next) {
  141.          if (strncmp(hist->line, str, len) == 0)
  142.             return (hist->line);
  143.       }
  144.       return (NULL);
  145.    case HM_REL:
  146.       for (hist = H_head; hist && num--; hist = hist->next);
  147.       return ((hist) ? hist->line : NULL);
  148.    case HM_ABS:
  149.       len = H_tail_base;
  150.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  151.       return ((hist) ? hist->line : NULL);
  152.    }
  153.    return (NULL);
  154. }
  155.  
  156. replace_head(str1, str2, flag)
  157. char *str1, *str2;
  158. {
  159.    char *str3;
  160.  
  161.    if (str1 == NULL)
  162.       str1 = "";
  163.    if (str2 == NULL) {
  164.       str2 = "";
  165.       flag = 0;
  166.    }
  167.    str3 = ((flag & (FL_EOC|FL_EOL)) == FL_EOC) ? ";" : " ";
  168.    if (H_head) {
  169.       free (H_head->line);
  170.       H_head->line = malloc (strlen(str1)+strlen(str2)+2);
  171.       strcpy (H_head->line, str1);
  172.       strcat (H_head->line, str3);
  173.       strcat (H_head->line, str2);
  174.    }
  175. }
  176.  
  177. perror(str)
  178. char *str;
  179. {
  180.    ierror(str, IoErr());
  181. }
  182.  
  183. ierror(str, err)
  184. char *str;
  185. {
  186.    struct PERROR *per = Perror;
  187.  
  188.    if (err) {
  189.       for (; per->errstr; ++per) {
  190.          if (per->errnum == err) {
  191.             printf ("%s%s%s\n",
  192.                   per->errstr,
  193.                   (str) ? ": " : "",
  194.                   (str) ? str : "");
  195.             return (err);
  196.          }
  197.       }
  198.       printf ("Unknown DOS error %d %s\n", err, (str) ? str : "");
  199.    }
  200.    return (err);
  201. }
  202.  
  203. /*
  204.  * Disk directory routines
  205.  *
  206.  * dptr = dopen(name, stat)
  207.  *    struct DPTR *dptr;
  208.  *    char *name;
  209.  *    int *stat;
  210.  *
  211.  * dnext(dptr, name, stat)
  212.  *    struct DPTR *dptr;
  213.  *    char **name;
  214.  *    int  *stat;
  215.  *
  216.  * dclose(dptr)                  -may be called with NULL without harm
  217.  *
  218.  * dopen() returns a struct DPTR, or NULL if the given file does not
  219.  * exist.  stat will be set to 1 if the file is a directory.  If the
  220.  * name is "", then the current directory is openned.
  221.  *
  222.  * dnext() returns 1 until there are no more entries.  The **name and
  223.  * *stat are set.  *stat = 1 if the file is a directory.
  224.  *
  225.  * dclose() closes a directory channel.
  226.  *
  227.  */
  228.  
  229. struct DPTR *
  230. dopen(name, stat)
  231. char *name;
  232. int *stat;
  233. {
  234.    struct DPTR *dp;
  235.    int namelen, endslash = 0;
  236.  
  237.    namelen = strlen(name);
  238.    if (namelen && name[namelen - 1] == '/') {
  239.       name[namelen - 1] = '\0';
  240.       endslash = 1;
  241.    }
  242.    *stat = 0;
  243.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  244.    if (*name == '\0')
  245.       dp->lock = DupLock (Clock);
  246.    else
  247.       dp->lock = Lock (name, ACCESS_READ);
  248.    if (endslash)
  249.       name[namelen - 1] = '/';
  250.    if (dp->lock == NULL) {
  251.       free (dp);
  252.       return (NULL);
  253.    }
  254.    dp->fib = (struct FileInfoBlock *)
  255.          AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  256.    if (!Examine (dp->lock, dp->fib)) {
  257.       perror (name);
  258.       dclose (dp);
  259.       return (NULL);
  260.    }
  261.    if (dp->fib->fib_DirEntryType >= 0)
  262.       *stat = 1;
  263.    return (dp);
  264. }
  265.  
  266. dnext(dp, pname, stat)
  267. struct DPTR *dp;
  268. char **pname;
  269. int *stat;
  270. {
  271.    if (dp == NULL)
  272.       return (0);
  273.    if (ExNext (dp->lock, dp->fib)) {
  274.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  275.       *pname = dp->fib->fib_FileName;
  276.       return (1);
  277.    }
  278.    return (0);
  279. }
  280.  
  281.  
  282. dclose(dp)
  283. struct DPTR *dp;
  284. {
  285.    if (dp == NULL)
  286.       return (1);
  287.    if (dp->fib)
  288.       FreeMem (dp->fib, sizeof(*dp->fib));
  289.    if (dp->lock)
  290.       UnLock (dp->lock);
  291.    free (dp);
  292.    return (1);
  293. }
  294.  
  295. free_expand(av)
  296. char **av;
  297. {
  298.    char **base = av;
  299.  
  300.    if (av) {
  301.       while (*av) {
  302.          free (*av);
  303.          ++av;
  304.       }
  305.       free (base);
  306.    }
  307. }
  308.  
  309. /*
  310.  * EXPAND(wild_name, pac)
  311.  *    wild_name      - char * (example: "df0:*.c")
  312.  *    pac            - int  *  will be set to # of arguments.
  313.  *
  314.  * Standalone, except in requires Clock to point to the Current-Directory
  315.  * lock.
  316.  */
  317.  
  318.  
  319. char **
  320. expand(base, pac)
  321. char *base;
  322. int *pac;
  323. {
  324.    char **eav = (char **)malloc (sizeof(char *));
  325.    int  eleft, eac;
  326.  
  327.    char *ptr, *name;
  328.    char *bname, *ename, *tail;
  329.    int stat, scr;
  330.    struct DPTR *dp;
  331.  
  332.    *pac = eleft = eac = 0;
  333.  
  334.    base = strcpy(malloc(strlen(base)+1), base);
  335.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  336.    for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  337.    if (ptr < base) {
  338.       bname = strcpy (malloc(1), "");
  339.    } else {
  340.       scr = ptr[1];
  341.       ptr[1] = '\0';
  342.       bname = strcpy (malloc(strlen(base)+1), base);
  343.       ptr[1] = scr;
  344.    }
  345.    ename = ptr + 1;
  346.    for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
  347.    scr = *ptr;
  348.    *ptr = '\0';
  349.    tail = (scr) ? ptr + 1 : NULL;
  350.  
  351.    if ((dp = dopen (bname, NULL, &stat)) == NULL  ||  stat == 0) {
  352.       free (bname);
  353.       free (base);
  354.       free (eav);
  355.       puts ("Could not open directory");
  356.       return (NULL);
  357.    }
  358.    while (dnext (dp, &name, &stat)) {
  359.       if (compare_ok(ename, name)) {
  360.          if (tail) {
  361.             int alt_ac;
  362.             char *search, **alt_av, **scrav;
  363.             struct FileLock *lock;
  364.  
  365.             if (!stat)           /* expect more dirs, but this not a dir */
  366.                continue;
  367.             lock = CurrentDir (Clock = dp->lock);
  368.             search = malloc(strlen(name)+strlen(tail)+2);
  369.             strcpy (search, name);
  370.             strcat (search, "/");
  371.             strcat (search, tail);
  372.             scrav = alt_av = expand (search, &alt_ac);
  373.             CurrentDir (Clock = lock);
  374.             if (scrav) {
  375.                while (*scrav) {
  376.                   if (eleft < 2) {
  377.                      char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  378.                      movmem (eav, scrav, sizeof(char *) * (eac + 1));
  379.                      free (eav);
  380.                      eav = scrav;
  381.                      eleft = 10;
  382.                   }
  383.                   eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
  384.                   strcpy(eav[eac], bname);
  385.                   strcat(eav[eac], *scrav);
  386.                   free (*scrav);
  387.                   ++scrav;
  388.                   --eleft, ++eac;
  389.                }
  390.                free (alt_av);
  391.             }
  392.          } else {
  393.             if (eleft < 2) {
  394.                char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  395.                movmem (eav, scrav, sizeof(char *) * (eac + 1));
  396.                free (eav);
  397.                eav = scrav;
  398.                eleft = 10;
  399.             }
  400.             eav[eac] = malloc (strlen(bname)+strlen(name)+1);
  401.             eav[eac] = strcpy(eav[eac], bname);
  402.             strcat(eav[eac], name);
  403.             --eleft, ++eac;
  404.          }
  405.       }
  406.    }
  407.    dclose (dp);
  408.    *pac = eac;
  409.    eav[eac] = NULL;
  410.    free (bname);
  411.    free (base);
  412.    if (eac)
  413.       return (eav);
  414.    free (eav);
  415.    return (NULL);
  416. }
  417.  
  418. /*
  419.  * Compare a wild card name with a normal name
  420.  */
  421.  
  422. #define MAXB   8
  423.  
  424. compare_ok(wild, name)
  425. char *wild, *name;
  426. {
  427.    char *w = wild;
  428.    char *n = name;
  429.    char *back[MAXB][2];
  430.    int  bi = 0;
  431.  
  432.    while (*n || *w) {
  433.       switch (*w) {
  434.       case '*':
  435.          if (bi == MAXB) {
  436.             puts ("Too many levels of '*'");
  437.             return (0);
  438.          }
  439.          back[bi][0] = w;
  440.          back[bi][1] = n;
  441.          ++bi;
  442.          ++w;
  443.          continue;
  444. goback:
  445.          --bi;
  446.          while (bi >= 0 && *back[bi][1] == '\0')
  447.             --bi;
  448.          if (bi < 0)
  449.             return (0);
  450.          w = back[bi][0] + 1;
  451.          n = ++back[bi][1];
  452.          ++bi;
  453.          continue;
  454.       case '?':
  455.          if (!*n) {
  456.             if (bi)
  457.                goto goback;
  458.             return (0);
  459.          }
  460.          break;
  461.       default:
  462.          if (*n != *w) {
  463.             if (bi)
  464.                goto goback;
  465.             return (0);
  466.          }
  467.          break;
  468.       }
  469.       if (*n)  ++n;
  470.       if (*w)  ++w;
  471.    }
  472.    return (1);
  473. }
  474.  
  475.  
  476.  
  477.